<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
	</head>
	<body>
		<button type="button" class="btn">btnClick</button>

		<button id="count">点击加</button>
		<button id="count2">点击减</button>
		<div id="show"></div>
		<script type="module">
			// import EventBus from './index.js'
			// 调度中心
			class EventBus {
				constructor() {
					// 事件集
					this.handles = {};
				}

				// 订阅事件
				on(eventType, handle) {
					if (!this.handles.hasOwnProperty(eventType)) {
						this.handles[eventType] = [];
					}
					if (typeof handle == 'function') {
						this.handles[eventType].push(handle);
					} else {
						throw new Error('缺少回调函数');
					}
					return this; // 实现链式操作
				}

				// 发布事件
				emit(eventType, ...args) {
					if (this.handles.hasOwnProperty(eventType)) {
						this.handles[eventType].forEach((item, key, arr) => {
							item.apply(null, args);
						});
					} else {
						throw new Error(eventType + "事件未注册");
					}
					return this; // 实现链式操作
				}

				// 取消订阅
				off(eventType, handle) {
					if (!this.handles.hasOwnProperty(eventType)) {
						throw new Error(eventType + "事件未注册");
					} else {
						this.handles[eventType].forEach((item, key, arr) => {
							if (item == handle) {
								arr.splice(key, 1);
							}
						});
					}
					return this; // 实现链式操作
				}
			}


			let eventBus = new EventBus();

			// 发布者
			class Publisher {
				constructor() {}

				lowPrice(price) {
					// 发布lowPrice事件
					eventBus.emit('lowPrice', price);
				}
			}

			// 订阅者
			class Subscriber {
				constructor() {}

				lowPriceHandle(price) {
					console.log("目前最低价是：" + price + "元");
				}

				getLowPrice() {
					// 订阅lowPrice事件
					eventBus.on('lowPrice', this.lowPriceHandle);
				}

				offLowPrice() {
					eventBus.off('lowPrice', this.lowPriceHandle);
				}
			}

			// 订阅者订阅了关于某个商品最新促销价的消息
			const subscriber = new Subscriber();
			subscriber.getLowPrice();

			// 发布者发布了某个商品的最新促销价
			const publisher = new Publisher();
			publisher.lowPrice(100); // test.html:76 目前最低价是：100元

			// 订阅者取消订阅
			subscriber.offLowPrice();
			publisher.lowPrice(200);
		</script>

		<script>
			{
				const body = document.querySelector(".btn")
				body.onclick = function() {
					// alert('btnClick');
				}
			}

			{
				document.body.addEventListener("click", function() {
					// alert('evClick');
				});
				document.body.click(); // 模拟用户点击
			}

			{
				/*
				 * publishSubscribe
				 */
				var eventExample = (function() {
					var clientList = {},
						listen,
						trigger,
						remove;
					listen = function(key, fun) {
						if (!clientList[key]) {
							clientList[key] = [];
						}
						clientList[key].push(fun);
					};
					trigger = function() {
						var key = Array.prototype.shift.call(arguments); // 获取订阅的key
						var funs = clientList[key]; // 取出订阅的事件列表
						// 如果没有订阅，不发消息
						if (!funs || funs.listen === 0) {
							return false;
						}
						for (let i = 0, fun;
							(fun = funs[i++]);) {
							fun.apply(this, arguments);
						}
					};
					remove = function(key, fun) {
						var funs = this.clientList[key];
						// 如果这个key对应的消息没有人订阅，直接返回
						if (!funs) {
							return false;
						}
						// 如果没有传入具体的回调函数，则取消所有的订阅
						if (!fun) {
							funs && (funs.listen = 0);
						} else {
							// 反向遍历订阅的回调函数列表
							for (let l = funs.length - 1; l > 0; l--) {
								var _fun = funs[l];
								// 碰到相同的回调函数，则删掉取消订阅
								if (_fun === fun) {
									funs.splice(l, 1);
								}
							}
						}
					};
					return {
						listen,
						trigger,
						remove,
					};
				})();

				eventExample.listen("橘子", function(price) {
					// console.log("价格=", price);
				});
				eventExample.trigger("橘子", 100);


				var a = (function() {
					var count = 0;
					var button = document.querySelector("#count");
					button.onclick = function() {
						eventExample.trigger("add", count++);
					};
					var button2 = document.querySelector("#count2");
					button2.onclick = function() {
						eventExample.trigger("remove", count--);
					};
				})();

				var b = (function() {
					var div = document.querySelector("#show");
					eventExample.listen("add", function(count) {
						div.innerHTML = count;
					});
					eventExample.listen("remove", function(count) {
						div.innerHTML = count;
					});
				})();
			}
		</script>
	</body>
</html>
